package cn.cosmosx.base.security;

import cn.cosmosx.base.constant.AuthSwitch;
import cn.cosmosx.base.filter.HttpServletRequestWrapperFilter;
import cn.cosmosx.base.filter.RequestEntryFinalKeeperFilter;
import cn.cosmosx.base.filter.XSSFilter;
import cn.cosmosx.base.security.exception.CustomAccessDeniedHandler;
import cn.cosmosx.base.security.exception.CustomAuthenticationEntryPoint;
import cn.cosmosx.base.security.filter.CustomFilterSecurityInterceptor;
import cn.cosmosx.base.security.filter.JWTAuthenticationFilter;
import cn.cosmosx.base.security.service.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.csrf.CsrfFilter;

/**
 * SpringSecurity配置类
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomUserDetailsService customUserDetailsService;
    @Autowired
    private RequestEntryFinalKeeperFilter requestEntryFinalKeeperFilter;
    @Autowired
    private HttpServletRequestWrapperFilter httpServletRequestWrapperFilter;
    @Autowired
    private XSSFilter xssFilter;
    @Autowired
    private JWTAuthenticationFilter jwtAuthenticationFilter;
    @Autowired
    private CustomFilterSecurityInterceptor customFilterSecurityInterceptor;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 允许跨域
        http.cors();

        // 禁用默认表单登录
        http
                .httpBasic().disable()
                .formLogin().disable()
                .logout().disable();

        // 禁用CSRF保护
        http.csrf().disable();

        // 禁用Session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // 基础过滤器
        http
                .addFilterBefore(requestEntryFinalKeeperFilter, CsrfFilter.class)
                .addFilterAfter(httpServletRequestWrapperFilter, RequestEntryFinalKeeperFilter.class)
                .addFilterAfter(xssFilter, HttpServletRequestWrapperFilter.class);

        // 动态权限绑定
        http
                .authorizeHttpRequests()
                .antMatchers(AuthSwitch.getWhiteList())
                .permitAll()
                .anyRequest()
                .authenticated();

        // 添加自定义过滤器
        http
                .addFilterAt(jwtAuthenticationFilter, FilterSecurityInterceptor.class)
                .addFilterAfter(customFilterSecurityInterceptor, JWTAuthenticationFilter.class);

        // 配置异常处理
        http
                .exceptionHandling()
                .accessDeniedHandler(new CustomAccessDeniedHandler())
                .authenticationEntryPoint(new CustomAuthenticationEntryPoint());

    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    @Bean("bCryptPasswordEncoder")
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
